1 00:00:00,110 --> 00:00:05,960 In this lecture, we're going to be taking a look at a feature in Roblox Studio called attributes. 2 00:00:05,990 --> 00:00:12,140 Attributes, as the name implies, allows you to add an attribute to any instance in the game. 3 00:00:12,140 --> 00:00:18,020 These attributes have a name, and they store a value, and this value can be accessed by any script 4 00:00:18,020 --> 00:00:18,740 in the game. 5 00:00:18,740 --> 00:00:22,700 You can basically think of it as like a global variable stored on a specific instance. 6 00:00:22,700 --> 00:00:27,560 And these can be very useful for defining things such as custom properties for stuff in your game. 7 00:00:27,560 --> 00:00:32,300 For example, if you had a gun and you wanted to track how much ammo was left in the magazine, you 8 00:00:32,300 --> 00:00:34,550 could have an attribute and store that number. 9 00:00:34,550 --> 00:00:40,040 Or if you wanted to store other stats for the gun, such as a reload duration, um, how much reserve 10 00:00:40,040 --> 00:00:40,670 ammo is left? 11 00:00:40,670 --> 00:00:42,530 You can also do that through attributes. 12 00:00:42,530 --> 00:00:47,420 Now to add an attribute on an instance in studio, you can just select your attribute. 13 00:00:47,420 --> 00:00:50,360 So for example, let me select the spawn location here. 14 00:00:50,360 --> 00:00:52,070 And inside of the properties menu. 15 00:00:52,070 --> 00:00:56,570 If we scroll down to the very bottom, there's going to be a section down here for attributes. 16 00:00:56,570 --> 00:00:58,880 And to add a new one we can just hit this plus button. 17 00:00:58,880 --> 00:01:03,650 And here we can define the name for the attribute and what type it's going to store. 18 00:01:03,650 --> 00:01:07,130 So currently these are all the different types that attributes can store. 19 00:01:07,130 --> 00:01:12,560 They can store strings booleans, numbers and some other Roblox data types such as vector threes, color 20 00:01:12,560 --> 00:01:14,840 threes, keyframes and stuff like that. 21 00:01:14,840 --> 00:01:17,450 You can't store functions or tables in here. 22 00:01:17,450 --> 00:01:19,610 That's just a limitation of attributes. 23 00:01:19,610 --> 00:01:24,200 But you can store all of these data types and attributes, and these should cover most use cases that 24 00:01:24,200 --> 00:01:25,880 you would use attributes for. 25 00:01:25,880 --> 00:01:27,470 So we could give a name for our attribute. 26 00:01:27,470 --> 00:01:28,520 I'll just say whatever. 27 00:01:28,520 --> 00:01:31,430 And this attribute is going to store a string so I can hit save. 28 00:01:31,430 --> 00:01:35,480 And now you can see our attribute shows up inside of the properties window. 29 00:01:35,480 --> 00:01:38,180 And currently it's storing an empty string. 30 00:01:38,180 --> 00:01:40,970 But I can type some text in here like hello there. 31 00:01:41,270 --> 00:01:46,880 And now I have stored this string with this particular instance which is my spawn location. 32 00:01:46,880 --> 00:01:48,830 And it has the name of whatever. 33 00:01:48,830 --> 00:01:51,290 So this is basically like a global variable. 34 00:01:51,290 --> 00:01:56,480 For this particular instance we can also add attributes to instances through scripts. 35 00:01:56,480 --> 00:01:58,190 And I'll show you how to do that right now. 36 00:01:58,190 --> 00:02:03,890 So for example let's refer to the spawn location inside of the workspace. 37 00:02:03,890 --> 00:02:07,070 And let's add another attribute on this instance. 38 00:02:07,070 --> 00:02:10,130 And we do that using a function called set attribute. 39 00:02:10,130 --> 00:02:15,830 And all we need to do is pass the name for the attribute and the value that we would like to store in 40 00:02:15,830 --> 00:02:16,610 the attribute. 41 00:02:16,610 --> 00:02:21,170 So let's call this attribute uh, whatever two. 42 00:02:21,170 --> 00:02:24,710 And inside of this attribute let's store a value of like 100. 43 00:02:24,710 --> 00:02:29,570 And then if I go and run this code here real quick, and then I take a look at my properties menu. 44 00:02:29,570 --> 00:02:32,300 As you can see, my whatever two here attribute has showed up. 45 00:02:32,300 --> 00:02:35,180 And it is storing the value of 100. 46 00:02:35,180 --> 00:02:41,780 Now if you would like to retrieve and read the value stored in an attribute, we can go ahead and refer 47 00:02:41,780 --> 00:02:46,190 to our spawn location and we have a get function called get attribute. 48 00:02:46,340 --> 00:02:51,050 And we need to provide the name of the attribute that we would like to read the value from. 49 00:02:51,050 --> 00:02:54,410 So we could read the value stored in whatever. 50 00:02:54,410 --> 00:02:57,260 And then we could also read the value stored in whatever two. 51 00:02:57,290 --> 00:03:00,590 So let's go ahead and print both of those out inside of the console. 52 00:03:01,190 --> 00:03:02,720 So I'll print that. 53 00:03:02,840 --> 00:03:08,540 And then let's go ahead and copy this code and print what is stored in whatever number two. 54 00:03:08,810 --> 00:03:11,660 And then let's go ahead and run this code and see what prints. 55 00:03:11,660 --> 00:03:12,800 And as you can see it prints. 56 00:03:12,800 --> 00:03:13,520 Hello there. 57 00:03:13,520 --> 00:03:16,190 And we get our value of 100 which is pretty cool. 58 00:03:16,190 --> 00:03:22,640 Now if you wanted to grab all of the attributes stored on an instance, then we have another get function 59 00:03:22,640 --> 00:03:26,660 and this one's called get attributes instead of get attribute. 60 00:03:26,660 --> 00:03:31,850 And you don't need to pass anything to this, but this function is going to return a dictionary that 61 00:03:31,850 --> 00:03:33,500 contains key value pairs. 62 00:03:33,500 --> 00:03:36,530 The key is going to be the names of the attributes. 63 00:03:36,530 --> 00:03:40,970 And then the value associated with that key is going to be whatever value is stored in that particular 64 00:03:40,970 --> 00:03:41,780 attribute. 65 00:03:41,780 --> 00:03:45,020 So let's go ahead and just print this out into the console. 66 00:03:45,020 --> 00:03:46,670 So we'll run our code again. 67 00:03:46,670 --> 00:03:47,960 And here we got our table. 68 00:03:47,960 --> 00:03:52,490 And there it shows our first attribute which is whatever storing the string of hello there. 69 00:03:52,490 --> 00:03:56,120 And then there is our other attribute with the value of 100. 70 00:03:56,120 --> 00:04:00,860 If you would like to be able to get rid of an attribute on an instance, for example, let's say I don't 71 00:04:00,860 --> 00:04:04,040 want this attribute of whatever two on my instance anymore. 72 00:04:04,070 --> 00:04:08,750 Then I can just simply set the value to nil, and that will automatically delete and get rid of that 73 00:04:08,750 --> 00:04:09,860 attribute on my instance. 74 00:04:09,860 --> 00:04:15,200 So if we run this code and then we go to the properties window, as you can see our whatever two attribute 75 00:04:15,200 --> 00:04:17,000 has disappeared because it got deleted. 76 00:04:17,000 --> 00:04:21,800 And then if you wanted to get rid of attributes inside of the properties window inside of studio, there's 77 00:04:21,800 --> 00:04:24,110 a little settings icon right here. 78 00:04:24,110 --> 00:04:28,160 And you can click that and you're able to delete or rename the attribute as well. 79 00:04:28,160 --> 00:04:33,650 Now since we want to make our games event driven as much as possible, there are some events that we 80 00:04:33,650 --> 00:04:36,260 can go ahead and listen to relating to attributes. 81 00:04:36,260 --> 00:04:42,620 So if we would like to listen for when an attribute changes on an instance, there is a property called 82 00:04:42,620 --> 00:04:47,690 attribute change and it says this fires whenever an attribute is changed on the instance. 83 00:04:47,810 --> 00:04:50,480 And we can go ahead and connect a function to this event. 84 00:04:50,480 --> 00:04:54,230 And this function is going to be passed the name of the attribute that changed. 85 00:04:54,230 --> 00:04:57,230 So we could call this attribute name. 86 00:04:57,560 --> 00:04:59,690 And then we'll just print out something like. 87 00:04:59,940 --> 00:05:02,100 Uh, attribute changed. 88 00:05:02,100 --> 00:05:06,420 And after we have connected this function to listen to this event, let's go ahead and add some more 89 00:05:06,420 --> 00:05:08,130 attributes to our spawn location. 90 00:05:08,130 --> 00:05:09,540 So we can do set attribute. 91 00:05:09,540 --> 00:05:11,490 Let's call this uh hello. 92 00:05:11,790 --> 00:05:14,580 And this attribute will just store some random value. 93 00:05:14,580 --> 00:05:18,060 And then let's go ahead and do it again set attribute. 94 00:05:18,060 --> 00:05:20,670 Let's call this one uh some color. 95 00:05:21,920 --> 00:05:24,470 And here we'll store a new color three. 96 00:05:25,280 --> 00:05:27,500 So we'll just do like white or something like that. 97 00:05:28,070 --> 00:05:30,260 And then let's go ahead and run this code. 98 00:05:30,860 --> 00:05:35,570 And what you're going to see is that our attribute changed event has fired twice. 99 00:05:35,570 --> 00:05:38,420 So attribute changed and attribute changed. 100 00:05:38,420 --> 00:05:44,630 And actually let's go ahead and swap this string here to actually print out the name of the attribute 101 00:05:44,630 --> 00:05:45,470 as well. 102 00:05:45,710 --> 00:05:47,540 And then let's run that code. 103 00:05:48,610 --> 00:05:52,360 And nothing printed because I think, yeah, these attributes are already here. 104 00:05:52,360 --> 00:05:57,160 So since we tried to set these attributes that already exist with the same value, nothing happens. 105 00:05:57,160 --> 00:06:01,060 So actually, let me just, uh, delete all of these real quick. 106 00:06:02,340 --> 00:06:05,310 Oh, you can actually see that it's listening and it's printing. 107 00:06:05,550 --> 00:06:06,780 Uh, that the attributes change. 108 00:06:06,780 --> 00:06:07,740 That's kind of cool. 109 00:06:07,740 --> 00:06:11,700 But if we go ahead and run this code again, what you're going to see is that hello. 110 00:06:11,700 --> 00:06:15,120 Changed, uh, some color change and it also printed attribute changed. 111 00:06:15,120 --> 00:06:17,550 I think I'm connecting a whole bunch of functions to this event. 112 00:06:17,550 --> 00:06:19,290 So I think that's why that's printing a bunch. 113 00:06:19,290 --> 00:06:24,060 Now, if you don't want to listen for when every single attribute on your instance changes and you only 114 00:06:24,060 --> 00:06:27,810 want to listen to a specific attribute, we have another function for that. 115 00:06:27,810 --> 00:06:31,320 And that function is called get attribute changed signal. 116 00:06:31,320 --> 00:06:35,040 And you just need to pass the name of the attribute that you would like to listen to. 117 00:06:35,040 --> 00:06:38,820 And this function will return an RGB script signal that we can connect to. 118 00:06:39,000 --> 00:06:44,340 So let's say uh, we want to listen for when the hello attribute changes. 119 00:06:44,340 --> 00:06:46,800 So we can pass our name of hello. 120 00:06:47,010 --> 00:06:49,950 And then we can connect a function to this. 121 00:06:50,280 --> 00:06:55,710 And we can just print something like the hello attribute changed. 122 00:06:55,980 --> 00:06:57,630 And then let me go ahead and run this code. 123 00:06:57,630 --> 00:06:59,310 So we're listening to that event. 124 00:06:59,310 --> 00:07:03,600 And then if I change the value inside of hello I'll do like uh something like this. 125 00:07:03,600 --> 00:07:04,590 Hit enter. 126 00:07:04,920 --> 00:07:08,880 It's going to print the hello attribute changed which is pretty cool. 127 00:07:08,880 --> 00:07:13,800 So as a simple exercise to get you started with attributes, I'd like for you to create a new part in 128 00:07:13,800 --> 00:07:14,970 your workspace. 129 00:07:14,970 --> 00:07:16,860 It doesn't have to be anything fancy. 130 00:07:16,860 --> 00:07:21,750 And what I would like for you to do is I would like for you to listen for when this part is touched, 131 00:07:21,750 --> 00:07:27,660 and every single time this part is touched, I want you to increment an attribute on the part that tells 132 00:07:27,660 --> 00:07:33,270 us how many times it has been touched so far in the lifetime of a particular server. 133 00:07:33,270 --> 00:07:36,990 So go ahead and spend a few minutes doing that, and then I'll show you my solution next. 134 00:07:37,470 --> 00:07:41,460 So what I'm going to do is I'm just going to add a simple script inside of my part. 135 00:07:41,550 --> 00:07:44,550 I'll make a variable for my part, which is script dot parent. 136 00:07:45,030 --> 00:07:49,590 And what we want to go ahead and do is we want to listen for when our part is touched. 137 00:07:49,590 --> 00:07:52,620 So we'll connect a function to that event. 138 00:07:52,620 --> 00:07:58,860 And every single time this event fires, we want to go ahead and increment an attribute on our part 139 00:07:58,860 --> 00:08:02,130 to represent how many times the part has been touched. 140 00:08:02,160 --> 00:08:08,040 Now, one way we could do it is we could have a variable in here, and we could call this touch count, 141 00:08:08,040 --> 00:08:09,390 and we could set it to zero. 142 00:08:09,390 --> 00:08:13,890 And every single time this event fires, we can increment touch count by one. 143 00:08:13,890 --> 00:08:16,590 And then on our part we can set an attribute. 144 00:08:16,590 --> 00:08:21,270 And we could call this, uh, times touched. 145 00:08:21,480 --> 00:08:24,030 And we could set it to the value of this touch count. 146 00:08:24,030 --> 00:08:26,460 That's one way we could use this with attributes. 147 00:08:26,460 --> 00:08:31,290 Or another way we could do it is that if we don't want to have any variable that keeps track in our 148 00:08:31,290 --> 00:08:36,270 script, how many times this part was touched and we only want to do it through attributes, what we 149 00:08:36,270 --> 00:08:41,190 can go ahead and do instead is we can make a variable here called touch count. 150 00:08:41,190 --> 00:08:42,990 And that's going to be equal to our part. 151 00:08:42,990 --> 00:08:47,010 And we're going to get the attribute of times touched. 152 00:08:47,010 --> 00:08:51,090 Now when this function first executes this attribute is not going to exist. 153 00:08:51,090 --> 00:08:54,600 So this is going to return the value of nil. 154 00:08:54,720 --> 00:09:02,160 So if touch count is nil that means we can go ahead and initialize touch count with a value of zero. 155 00:09:02,160 --> 00:09:07,410 Now a faster way of doing this without needing to use an if statement, is that we could add an Or statement 156 00:09:07,410 --> 00:09:08,730 here and put a zero. 157 00:09:08,730 --> 00:09:12,480 And now this zero value is acting as a default value. 158 00:09:12,480 --> 00:09:18,690 So just in case this function right here returns nil, it'll instead see this or statement and see hey 159 00:09:18,690 --> 00:09:19,500 there's a value here. 160 00:09:19,500 --> 00:09:23,250 We're going to use this instead because this function returned nil. 161 00:09:23,250 --> 00:09:28,020 And then afterwards we can go ahead and increment touched count by one. 162 00:09:28,020 --> 00:09:31,920 And then we can go ahead and set that attribute on our part. 163 00:09:31,920 --> 00:09:37,290 So now as we're playing the game I haven't touched the part yet, but you'll notice that the times touched 164 00:09:37,290 --> 00:09:38,850 attribute is actually set to one. 165 00:09:38,850 --> 00:09:43,920 And I believe that's probably because my part is unanchored and it touched the base plate, and that's 166 00:09:43,920 --> 00:09:44,760 why I incremented. 167 00:09:44,760 --> 00:09:50,070 But if I go ahead and walk over my part and start touching it, you're going to see that my times touched 168 00:09:50,070 --> 00:09:53,970 attribute is increasing every single time I touched it, which is pretty cool. 169 00:09:53,970 --> 00:09:57,330 And we are able to read this attribute from any other script on our game. 170 00:09:57,330 --> 00:10:02,280 So if we had another script inside of Server Script service, it would be able to refer to this part 171 00:10:02,280 --> 00:10:07,200 and use the get attribute function to read the attribute that is stored on this part. 172 00:10:07,200 --> 00:10:11,160 We can see it here on the client, and if I swap to the server view and I select this part. 173 00:10:11,160 --> 00:10:14,880 As you can see, the server can see this attribute on the part as well. 174 00:10:14,880 --> 00:10:20,640 Now if I was on the client here and let's say the client added a new attribute, I'll just call this 175 00:10:20,640 --> 00:10:22,200 example the client. 176 00:10:22,200 --> 00:10:25,680 And any scripts on the client is going to see this attribute. 177 00:10:25,680 --> 00:10:30,900 But if I swap to the server view, what you're going to notice is that of course the server does not 178 00:10:30,900 --> 00:10:36,450 see that attribute because we applied or added the attribute on the client, and only the client can 179 00:10:36,450 --> 00:10:38,250 see those client sided changes. 180 00:10:38,250 --> 00:10:45,210 The reason attributes were added were to act as maybe an alternative or a replacement to the previous 181 00:10:45,210 --> 00:10:45,720 way. 182 00:10:45,720 --> 00:10:51,690 Developers used to store values on instances or share them across multiple scripts, and that was with 183 00:10:51,690 --> 00:10:52,890 value objects. 184 00:10:52,890 --> 00:10:57,780 So if I were to search value here, as you can see, there's a whole bunch of different instances in 185 00:10:57,780 --> 00:11:01,620 the game such as Vector3 values, string value, object value. 186 00:11:01,800 --> 00:11:03,360 And all of these different values here. 187 00:11:03,360 --> 00:11:08,580 And if I were to add one of these in here, this is simply an instance that stores that particular value. 188 00:11:08,580 --> 00:11:12,450 So for example, this stores a true or a false value. 189 00:11:12,480 --> 00:11:18,060 Or if I were to add a keyframe value here, of course this stores a keyframe. 190 00:11:18,060 --> 00:11:22,650 Now if you don't want to do it through these instances, and you would like for all of these values 191 00:11:22,650 --> 00:11:27,330 to be stored directly on the instance, then you can do so with attributes. 192 00:11:27,330 --> 00:11:30,420 So those are attributes in a nutshell. 193 00:11:30,420 --> 00:11:33,750 You'll likely find them useful in many situations in your games. 194 00:11:33,750 --> 00:11:36,870 And we're also going to be using attributes in our upcoming project. 195 00:11:36,870 --> 00:11:39,810 So stay tuned and I will see you in the next lecture.